using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

namespace EntityKit.Editor
{
    public class FindMissingScriptsWindow : EditorWindow
    {
        private Vector2 m_ScrollPosition;
        private List<GameObject> m_MissingScriptObjects = new List<GameObject>();
        private List<Object> m_PrefabsWithMissingScripts = new List<Object>();
        private enum SearchMode { Scene, Prefabs }
        private SearchMode m_SearchMode = SearchMode.Scene;
        private enum PrefabSearchMode { All, Folder, Single }
        private PrefabSearchMode m_PrefabSearchMode = PrefabSearchMode.All;
        private string m_PrefabsPath = "Assets";
        private Object m_SinglePrefab;
        private Rect m_FolderPathRect;
        
        // 界面相关
        private GUIStyle m_HeaderStyle;
        private GUIStyle m_TitleStyle;
        private GUIStyle m_SubtitleStyle;
        private GUIStyle m_BoxStyle;
        private GUIStyle m_ResultBoxStyle;
        private GUIStyle m_ResultItemStyle;
        private GUIStyle m_ButtonStyle;
        private bool m_StylesInitialized = false;
        private Texture2D m_HeaderBackground;
        private Color m_DefaultBackgroundColor;
        
        public static void ShowWindow()
        {
            var window = GetWindow<FindMissingScriptsWindow>("查找丢失脚本");
            window.minSize = new Vector2(400, 500);
            window.Show();
        }

        void OnGUI()
        {
            InitializeStyles();
            DrawHeader();
            DrawSearchSettings();
            DrawActionButtons();
            DrawResults();
        }

        void InitializeStyles()
        {
            if (m_StylesInitialized) return;

            // 标题样式
            m_TitleStyle = new GUIStyle(EditorStyles.largeLabel);
            m_TitleStyle.fontStyle = FontStyle.Bold;
            m_TitleStyle.fontSize = 20;
            m_TitleStyle.normal.textColor = EditorGUIUtility.isProSkin ? Color.white : Color.black;
            m_TitleStyle.alignment = TextAnchor.MiddleCenter;
            
            // 副标题样式
            m_SubtitleStyle = new GUIStyle(EditorStyles.label);
            m_SubtitleStyle.fontStyle = FontStyle.Normal;
            m_SubtitleStyle.fontSize = 12;
            m_SubtitleStyle.normal.textColor = EditorGUIUtility.isProSkin ? new Color(0.7f, 0.7f, 0.7f) : new Color(0.4f, 0.4f, 0.4f);
            m_SubtitleStyle.alignment = TextAnchor.MiddleCenter;

            // 盒子样式
            m_BoxStyle = new GUIStyle(EditorStyles.helpBox);
            m_BoxStyle.padding = new RectOffset(10, 10, 10, 10);
            m_BoxStyle.margin = new RectOffset(10, 10, 5, 5);

            // 结果盒子样式
            m_ResultBoxStyle = new GUIStyle(EditorStyles.helpBox);
            m_ResultBoxStyle.padding = new RectOffset(10, 10, 10, 10);
            m_ResultBoxStyle.margin = new RectOffset(10, 10, 5, 5);

            // 结果项样式
            m_ResultItemStyle = new GUIStyle(EditorStyles.label);
            m_ResultItemStyle.padding = new RectOffset(5, 5, 5, 5);
            m_ResultItemStyle.margin = new RectOffset(0, 0, 0, 0);

            // 按钮样式
            m_ButtonStyle = new GUIStyle(GUI.skin.button);
            m_ButtonStyle.padding = new RectOffset(10, 10, 10, 10);
            m_ButtonStyle.margin = new RectOffset(5, 5, 5, 5);
            m_ButtonStyle.fontStyle = FontStyle.Bold;

            // 创建头部背景
            m_HeaderBackground = new Texture2D(1, 1);
            m_HeaderBackground.SetPixel(0, 0, EditorGUIUtility.isProSkin ? 
                new Color(0.25f, 0.25f, 0.25f) : 
                new Color(0.85f, 0.85f, 0.85f));
            m_HeaderBackground.Apply();

            m_StylesInitialized = true;
        }

        void DrawHeader()
        {
            // 绘制头部背景
            var headerRect = EditorGUILayout.GetControlRect(false, 80);
            GUI.DrawTexture(headerRect, m_HeaderBackground, ScaleMode.StretchToFill);
            
            // 绘制标题
            var titleRect = new Rect(headerRect.x, headerRect.y + 20, headerRect.width, 30);
            GUI.Label(titleRect, "查找丢失脚本组件", m_TitleStyle);
            
            // 绘制副标题
            var subtitleRect = new Rect(headerRect.x, headerRect.y + 50, headerRect.width, 20);
            GUI.Label(subtitleRect, "快速定位项目中丢失的脚本组件", m_SubtitleStyle);
            
            EditorGUILayout.Space();
        }

        void DrawSearchSettings()
        {
            EditorGUILayout.BeginVertical(m_BoxStyle);
            
            GUILayout.Label("搜索配置", EditorStyles.boldLabel);
            
            // 搜索模式选择
            EditorGUI.BeginChangeCheck();
            m_SearchMode = (SearchMode)EditorGUILayout.EnumPopup("搜索模式", m_SearchMode);
            if (EditorGUI.EndChangeCheck())
            {
                // 清除之前的结果
                m_MissingScriptObjects.Clear();
                m_PrefabsWithMissingScripts.Clear();
            }

            if (m_SearchMode == SearchMode.Scene)
            {
                EditorGUILayout.HelpBox("将在当前场景中查找包含丢失脚本的对象", MessageType.Info);
            }
            else
            {
                // Prefab搜索模式选择
                m_PrefabSearchMode = (PrefabSearchMode)EditorGUILayout.EnumPopup("Prefab搜索模式", m_PrefabSearchMode);
                
                switch (m_PrefabSearchMode)
                {
                    case PrefabSearchMode.Folder:
                        GUILayout.BeginHorizontal();
                        // 禁用手动编辑，只允许拖拽或浏览选择
                        GUI.enabled = false;
                        EditorGUILayout.TextField("Prefabs路径", m_PrefabsPath);
                        GUI.enabled = true;
                        
                        if (GUILayout.Button("浏览", GUILayout.Width(60)))
                        {
                            string selectedPath = EditorUtility.OpenFolderPanel("选择Prefabs文件夹", "Assets", "");
                            if (!string.IsNullOrEmpty(selectedPath))
                            {
                                if (selectedPath.StartsWith(Application.dataPath))
                                {
                                    m_PrefabsPath = "Assets" + selectedPath.Substring(Application.dataPath.Length);
                                }
                                else
                                {
                                    EditorUtility.DisplayDialog("错误", "请选择项目Assets文件夹内的路径", "确定");
                                }
                            }
                        }
                        GUILayout.EndHorizontal();
                        
                        // 记录路径输入框的矩形区域用于拖拽检测
                        m_FolderPathRect = GUILayoutUtility.GetLastRect();
                        // 在这里直接处理拖拽，确保在正确的位置处理
                        HandleFolderDragAndDrop(m_FolderPathRect);
                        break;
                        
                    case PrefabSearchMode.Single:
                        // Unity的ObjectField本身就支持拖拽，无需额外处理
                        m_SinglePrefab = EditorGUILayout.ObjectField("选择Prefab", m_SinglePrefab, typeof(GameObject), false);
                        break;
                        
                    case PrefabSearchMode.All:
                        EditorGUILayout.HelpBox("将在整个项目中查找包含丢失脚本的Prefab", MessageType.Info);
                        break;
                }
            }
            
            EditorGUILayout.EndVertical();
            EditorGUILayout.Space();
        }

        void DrawActionButtons()
        {
            EditorGUILayout.BeginHorizontal();
            
            if (GUILayout.Button("开始搜索", m_ButtonStyle, GUILayout.Height(40)))
            {
                FindMissingScripts();
            }

            if (GUILayout.Button("清除结果", m_ButtonStyle, GUILayout.Height(40)))
            {
                m_MissingScriptObjects.Clear();
                m_PrefabsWithMissingScripts.Clear();
                Repaint();
            }
            
            EditorGUILayout.EndHorizontal();
            EditorGUILayout.Space();
        }

        void DrawResults()
        {
            int totalCount = m_MissingScriptObjects.Count + m_PrefabsWithMissingScripts.Count;
            
            EditorGUILayout.BeginVertical(m_ResultBoxStyle);
            
            GUILayout.Label($"搜索结果 ({totalCount} 个对象)", EditorStyles.boldLabel);
            
            m_ScrollPosition = EditorGUILayout.BeginScrollView(m_ScrollPosition, GUILayout.ExpandHeight(false));
            
            if (totalCount == 0)
            {
                GUILayout.FlexibleSpace();
                GUILayout.BeginHorizontal();
                GUILayout.FlexibleSpace();
                
                var emptyStyle = new GUIStyle(EditorStyles.label);
                emptyStyle.alignment = TextAnchor.MiddleCenter;
                emptyStyle.normal.textColor = EditorGUIUtility.isProSkin ? 
                    new Color(0.7f, 0.7f, 0.7f) : 
                    new Color(0.4f, 0.4f, 0.4f);
                
                GUILayout.Label("点击\"开始搜索\"按钮查找丢失的脚本", emptyStyle);
                GUILayout.FlexibleSpace();
                GUILayout.EndHorizontal();
                GUILayout.FlexibleSpace();
            }
            else
            {
                // 显示场景中丢失脚本的对象
                if (m_MissingScriptObjects.Count > 0)
                {
                    GUILayout.Label($"场景中的对象 ({m_MissingScriptObjects.Count})", EditorStyles.boldLabel);
                    
                    for (int i = 0; i < m_MissingScriptObjects.Count; i++)
                    {
                        if (m_MissingScriptObjects[i] != null)
                        {
                            GUILayout.BeginHorizontal(m_ResultItemStyle);
                            
                            // 显示层级结构
                            string hierarchy = GetGameObjectHierarchyPath(m_MissingScriptObjects[i]);
                            EditorGUILayout.ObjectField(hierarchy, m_MissingScriptObjects[i], typeof(GameObject), true);
                            
                            if (GUILayout.Button("选择", GUILayout.Width(60), GUILayout.Height(18)))
                            {
                                Selection.activeGameObject = m_MissingScriptObjects[i];
                            }
                            
                            GUILayout.EndHorizontal();
                        }
                        else
                        {
                            GUILayout.BeginHorizontal(m_ResultItemStyle);
                            EditorGUILayout.LabelField($"[{i}] 已销毁的对象");
                            GUILayout.EndHorizontal();
                        }
                    }
                }

                // 显示Prefab中丢失脚本的对象
                if (m_PrefabsWithMissingScripts.Count > 0)
                {
                    GUILayout.Label($"Prefabs中的对象 ({m_PrefabsWithMissingScripts.Count})", EditorStyles.boldLabel);
                    
                    for (int i = 0; i < m_PrefabsWithMissingScripts.Count; i++)
                    {
                        if (m_PrefabsWithMissingScripts[i] != null)
                        {
                            GUILayout.BeginHorizontal(m_ResultItemStyle);
                            EditorGUILayout.ObjectField(m_PrefabsWithMissingScripts[i], typeof(Object), false);
                            
                            if (GUILayout.Button("定位", GUILayout.Width(60), GUILayout.Height(18)))
                            {
                                EditorGUIUtility.PingObject(m_PrefabsWithMissingScripts[i]);
                            }
                            
                            GUILayout.EndHorizontal();
                        }
                        else
                        {
                            GUILayout.BeginHorizontal(m_ResultItemStyle);
                            EditorGUILayout.LabelField($"[{i}] 丢失的Prefab");
                            GUILayout.EndHorizontal();
                        }
                    }
                }
            }
            
            EditorGUILayout.EndScrollView();
            EditorGUILayout.EndVertical();
        }

        void FindMissingScripts()
        {
            m_MissingScriptObjects.Clear();
            m_PrefabsWithMissingScripts.Clear();

            if (m_SearchMode == SearchMode.Scene)
            {
                FindMissingScriptsInScene();
            }
            else
            {
                switch (m_PrefabSearchMode)
                {
                    case PrefabSearchMode.All:
                        FindMissingScriptsInAllPrefabs();
                        break;
                    case PrefabSearchMode.Folder:
                        FindMissingScriptsInPrefabs();
                        break;
                    case PrefabSearchMode.Single:
                        FindMissingScriptsInSinglePrefab();
                        break;
                }
            }
            
            // 刷新界面
            Repaint();
        }

        void FindMissingScriptsInScene()
        {
            GameObject[] allGameObjects = Resources.FindObjectsOfTypeAll<GameObject>();

            foreach (GameObject go in allGameObjects)
            {
                // 只检查场景中的对象，不检查Prefab
                if (go.hideFlags == HideFlags.NotEditable || go.hideFlags == HideFlags.HideAndDontSave)
                    continue;

                if (PrefabUtility.IsPartOfPrefabAsset(go))
                    continue;

                // 只添加真正包含丢失脚本的对象，而不是包含丢失脚本对象的父对象
                if (HasMissingScriptComponent(go) && !PrefabUtility.IsPrefabAssetMissing(go))
                {
                    m_MissingScriptObjects.Add(go);
                }
            }
        }

        void FindMissingScriptsInAllPrefabs()
        {
            string[] guids = AssetDatabase.FindAssets("t:Prefab", null);

            foreach (string guid in guids)
            {
                string path = AssetDatabase.GUIDToAssetPath(guid);
                GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);

                if (prefab != null && HasMissingScript(prefab))
                {
                    m_PrefabsWithMissingScripts.Add(prefab);
                }
            }
        }

        void FindMissingScriptsInPrefabs()
        {
            string[] guids = AssetDatabase.FindAssets("t:Prefab", new string[] { m_PrefabsPath });

            foreach (string guid in guids)
            {
                string path = AssetDatabase.GUIDToAssetPath(guid);
                GameObject prefab = AssetDatabase.LoadAssetAtPath<GameObject>(path);

                if (prefab != null && HasMissingScript(prefab))
                {
                    m_PrefabsWithMissingScripts.Add(prefab);
                }
            }
        }

        void FindMissingScriptsInSinglePrefab()
        {
            if (m_SinglePrefab != null)
            {
                GameObject prefab = m_SinglePrefab as GameObject;
                if (prefab != null)
                {
                    // 查找Prefab中所有包含丢失脚本的节点
                    FindMissingScriptsInGameObject(prefab);
                }
            }
        }
        
        // 在GameObject及其子对象中查找所有包含丢失脚本的节点
        void FindMissingScriptsInGameObject(GameObject go)
        {
            // 检查当前对象是否包含丢失的脚本组件
            if (HasMissingScriptComponent(go))
            {
                m_PrefabsWithMissingScripts.Add(go);
            }
            
            // 递归检查子对象
            foreach (Transform child in go.transform)
            {
                FindMissingScriptsInGameObject(child.gameObject);
            }
        }

        // 检查对象本身是否有丢失的脚本组件（不递归检查子对象）
        bool HasMissingScriptComponent(GameObject go)
        {
            Component[] components = go.GetComponents<Component>();

            foreach (Component component in components)
            {
                if (component == null)
                {
                    return true;
                }
            }

            return false;
        }

        bool HasMissingScript(GameObject go)
        {
            if (HasMissingScriptComponent(go))
            {
                return true;
            }

            // 递归检查子对象
            foreach (Transform child in go.transform)
            {
                if (HasMissingScript(child.gameObject))
                {
                    return true;
                }
            }

            return false;
        }
        
        string GetGameObjectHierarchyPath(GameObject obj)
        {
            if (obj == null) return "";
            
            string path = obj.name;
            Transform parent = obj.transform.parent;
            
            while (parent != null)
            {
                path = parent.name + "/" + path;
                parent = parent.parent;
            }
            
            return path;
        }
        
        // 处理文件夹拖拽
        void HandleFolderDragAndDrop(Rect dropArea)
        {
            Event evt = Event.current;
            switch (evt.type)
            {
                case EventType.DragUpdated:
                case EventType.DragPerform:
                    if (!dropArea.Contains(evt.mousePosition))
                        return;

                    DragAndDrop.visualMode = DragAndDropVisualMode.Copy;

                    if (evt.type == EventType.DragPerform)
                    {
                        DragAndDrop.AcceptDrag();
                        
                        // 处理从Project窗口拖入的文件夹
                        foreach (Object obj in DragAndDrop.objectReferences)
                        {
                            // 检查是否为文件夹 (DefaultAsset且对应路径是文件夹)
                            if (obj is DefaultAsset)
                            {
                                string path = AssetDatabase.GetAssetPath(obj);
                                if (!string.IsNullOrEmpty(path))
                                {
                                    // 检查路径是否为文件夹
                                    string fullPath = Application.dataPath.Substring(0, Application.dataPath.Length - 6) + path;
                                    if (System.IO.Directory.Exists(fullPath))
                                    {
                                        m_PrefabsPath = path;
                                        Repaint();
                                        return;
                                    }
                                }
                            }
                        }
                        
                        // 处理从系统文件浏览器拖入的文件夹
                        foreach (string path in DragAndDrop.paths)
                        {
                            if (System.IO.Directory.Exists(path))
                            {
                                if (path.StartsWith(Application.dataPath))
                                {
                                    m_PrefabsPath = "Assets" + path.Substring(Application.dataPath.Length);
                                    Repaint();
                                    return;
                                }
                            }
                        }
                    }
                    break;
            }
        }
        
        void OnDestroy()
        {
            if (m_HeaderBackground != null)
            {
                DestroyImmediate(m_HeaderBackground);
            }
        }
    }
}